home *** CD-ROM | disk | FTP | other *** search
- #!/usr/app/bin/perl
-
- eval 'exec /usr/app/bin/perl -S $0 ${1+"$@"}'
- if 0; # not running under some shell
-
- #
- # Note: Seth has transferred the maintainer `position' to me, so bother me
- # instead of him now :-)
- # - Steinar H. Gunderson <sgunderson@bigfoot.com>
-
-
- # This one's all mine. Well, its GPL/Artisitic but I'm the author and creator.
- # You need gimp 1.1 or better for this; too much has changed, and I don't think
- # 1.0.x had a perspective PDB function anyway
-
- # Here's the working theory on this:
- # There's a function called spinlayer which will spin from a spinlayer to a
- # destlayer. It won't touch those 2 layers at all, and will leave its results
- # on the top of the layer stack.
- #
- # If the user wants to spin back, it will take 1/2 the layers otherwise required
- # per call to the spin_layer, so that the number of total layers comes out the
- # same.
- #
- # The main function makes a new image, copies the source and destination onto it
- # with appropriate offsets, and passes this image with the bottom 2 layers to
- # spin_layer. At the end, remove the original 2 layers, since they won't be
- # needed, and add in some Layer comments for timing your gif.
- #
- ################################################################################
- # Many thanks to Steinar and Marc, for expressing an intrest in the script that
- # kept me going, and to Steinar in particular for helping me track down why the
- # script was crashing gimp (hint - don't make layers of height=0, and if you do
- # make sure you're logging to console since the Gtk messagebox will never show
- # up due to a rapid segfault).
- #
- # Just a comment on that: We fixed the bug, so height=0 no longer segfaults, but
- # gives the error message it should. However, if GIMP segfaults, you should try
- # logging to console to make sure you get all applicable error messages. This
- # will make it _much_ easier to find the bug. - Steinar
- #
- # Revision History:
- # 1.0 - Initial (too early) release
- # 1.1 - Second (still ugly) release: Made the perspective setting actually do
- # something
- # 1.2 - Used some of the convienence functions, and made things a little eaiser
- # from the user's standpoint too. Also moved it from the
- # Filters->Animations-> menu to Xtns->Animations. I think its
- # clearer whats going on this way. It also works w/ any 2 layers now.
- # 1.5 - Some debugging by Steinar and myself to make it work again.
- # 1.6 - Moved some renaming into the main loop, more cleanups.
- #
- # TODO: Clean it up; allow for other effects (skewing, ripples?) while spinning;
-
- # Seth Burgess
- # <sjburges@gimp.org>
-
- use Gimp; # No qw(:auto) - Trying to use all OO-styling
- use Gimp::Fu;
- use Gimp::Util;
-
- # Gimp::set_trace(TRACE_ALL);
-
- sub saw { # a sawtooth function on PI
- ($val) = @_;
- if ($val < 3.14159/2.0) {
- return ($val/3.14159);
- } elsif ($val < 3.14159) {
- return (-1+$val/3.14159);
- } elsif ($val < 3.14159+3.14159/2.0) {
- return ($val/3.14159);
- } else {
- return (-1+$val/3.14159);
- }
- }
-
- sub spin_layer { # the function for actually spinning the layer
- my ($img, $spin, $dest, $numframes, $prp) = @_;
-
- my $floater, # The transformed image
- $framelay, # The background color
- $frameno; # The current frame
-
- # Now let's spin it!
- $stepsize = 3.14159/$numframes; # in radians
- $frameno = 0;
- for ($i=0; $i<=3.14159; $i+=$stepsize) {
- Gimp->progress_update ($i/3.14159);
-
- # create a new layer for spinning
- $framelay = ($i < 3.14159/2.0) ? $spin->copy(1) : $dest->copy(1);
- $img->add_layer($framelay, 0);
- $floater = $framelay->copy(1);
- $img->add_layer($floater, 0);
-
- # spin it a step
- $img->selection_all();
- @x = $img->selection_bounds();
- $img->selection_none();
-
- # x[1],x[2] x[3],x[2]
- # x[1],x[4] x[3],x[4]
- my($y1, $y3);
- $y1 = int($x[2]+$spin->height *sin($i)/2);
- $y3 = int($x[4]-$spin->height *sin($i)/2);
-
- # height must be != 0
- $y3++ if ($y1 == $y3);
-
- $floater = Gimp->perspective($floater, 1,
- $x[1]+saw($i)*$prp*$framelay->width,$y1,
- $x[3]-saw($i)*$prp*$framelay->width,$y1,
- $x[1]-saw($i)*$prp*$framelay->width,$y3,
- $x[3]+saw($i)*$prp*$framelay->width,$y3);
- $framelay->fill(1); # BG-IMAGE-FILL
-
- # merge the two layers together before we continue
- $img->set_visible($floater, $framelay);
- $framelay = $img->merge_visible_layers(0);
-
- $frameno++;
- $framelay->set_name("Spin Layer $frameno (50ms)");
- }
- }
-
- register "seth_spin",
- "Seth Spin",
- "Take one image. Spin it about the horizontal axis, and end up with another image. I made it for easy web buttons.",
- "Seth Burgess",
- "Seth Burgess <sjburges\@gimp.org>",
- "1.6",
- N_"<Toolbox>/Xtns/Animation/Seth Spin...",
- "*",
- [
- [PF_DRAWABLE, "source", "What drawable to spin from?"],
- [PF_DRAWABLE, "destination","What drawable to spin to?"],
- [PF_INT8, "frames", "How many frames to use?", 16],
- [PF_COLOR, "background", "What color to use for background if not transparent", [0,0,0]],
- [PF_SLIDER, "perspective", "How much perspective effect to get", 40, [0,255,5]],
- [PF_TOGGLE, "spin_back", "Also spin back?" , 1],
- [PF_TOGGLE, "convert_indexed", "Convert to indexed?", 1],
- ],
- [],
- ['gimp-1.1'],
- sub {
- my($src,$dest,$frames,$color,$perspective,$spinback,$indexed) = @_;
-
- $oldbackground = Gimp->palette_get_background();
- Gimp->palette_set_background($color);
-
- $perspective = $perspective/255.0; # PF_SLIDER doesn't work right for < 1
-
- Gimp->progress_init(__"Seth Spin...",-1);
-
- # Copy souce and destination to new image
-
- $maxwide = ($src->width > $dest->width) ? $src->width : $dest->width;
- $maxhigh = ($src->height > $dest->height) ? $src->height: $dest->height;
-
- $img = Gimp->image_new($maxwide, $maxhigh, RGB);
- $tmpimglayer = $img->add_new_layer(0,3,1); # have to have a layer before displaying
- $img->display_new;
-
- $src->edit_copy();
- $spinlayer = $tmpimglayer->edit_paste(1);
- $spinlayer->floating_sel_to_layer();
-
- $dest->edit_copy();
- $destlayer = $tmpimglayer->edit_paste(1);
- $destlayer->floating_sel_to_layer();
-
- $tmpimglayer->remove_layer; # remove temporary layer.
-
- # set the layer size to be the full layer for each copied layer
- $spinlayer->resize($maxwide, $maxhigh, $spinlayer->offsets);
- $destlayer->resize($maxwide, $maxhigh, $destlayer->offsets);
-
- # need an even number of frames for spinback
- if ($frames%2 && $spinback) {
- $frames++;
- Gimp->message(__"An even number of frames is needed for spin back.\nAdjusted frames up to $frames");
- }
-
- spin_layer($img, $spinlayer, $destlayer, $spinback ? $frames/2 : $frames, $perspective);
-
- # go back from destination to spinlayer if spinning back
- if ($spinback) {
- @layerlist = $img->get_layers();
- spin_layer($img, $destlayer, $spinlayer, $frames/2, $perspective);
- }
-
- # remove the original 2 pasted layers
- $img->remove_layer($destlayer);
- $img->remove_layer($spinlayer);
-
- # unhide and name layers (Give timings)
- @all_layers = $img->get_layers;
- $img->set_visible(@all_layers);
-
- if ($spinback) {
- $all_layers[$frames/2-1]->set_name(__"Spin Layer DEST (250ms)");
- }
- $all_layers[$frames-1]->set_name(__"Spin Layer SRC (250ms)");
-
- # indexed conversion wants a display for some reason
- if ($indexed) {
- $img->convert_indexed(1,MAKE_PALETTE,255,0,1,"buffy" );
- }
-
- Gimp->palette_set_background($oldbackground);
- return();
- };
-
- exit main;
-
-